package daos

import (
	"bsm/logger"
	"bsm/models"

	"github.com/jmoiron/sqlx"
)

type ExportDao interface {
	GetProjectBase(pcode string, atype int) (*models.ExportBase, error)
	GetLaborTable(pcode string, atype int) ([]models.ExportXlsxTab3, error)
	GetMaterialTable(pcode string, atype int) ([]models.ExportXlsxTab4, error)
	GetOtherFeeTable(pcode string, atype int) ([]models.ExportXlsxTab5, error)
	GetUserByID(userID string) (models.ProjectUser, error)
	GetOrgByProjectCode(pcode string) (models.Org, error)
}

type exportDaoImpl struct {
	dbExport *sqlx.DB
}

func NewExportDao(dbExport *sqlx.DB) ExportDao {
	return &exportDaoImpl{
		dbExport: dbExport,
	}
}

func (dao *exportDaoImpl) GetProjectBase(pcode string, designtype int) (*models.ExportBase, error) {
	var prjBase models.ExportBase
	// query := "SELECT name, design_code, project_state,org_code,designer, reviewer, initiator, project_type, business_type,construction_type,project_overview, technical_analysis,profit_statement,preparation_date,time_budget,time_settle,time_audit  FROM project_base WHERE design_code=?"

	query := "select name, design_code, designer, reviewer, preparation_date,initiator,  business_type,construction_type,project_overview, technical_analysis,profit_statement,point_old,point_new,point_cost,recycle_cycle,time_budget,time_settle,time_audit from project_base where design_code=? "

	//args := []interface{}{pcode}
	err := dao.dbExport.Get(&prjBase, query, pcode)
	if err != nil {
		logger.Errorf("failed to get project base: %v", err)
		return &models.ExportBase{}, err
	}
	return &prjBase, nil
}

// 计算表三导出人工数据（包含系数）  （这里暂时缺少台班及仪表计算）
func (dao *exportDaoImpl) GetLaborTable(pcode string, designtype int) ([]models.ExportXlsxTab3, error) {
	var laborItems []models.ExportXlsxTab3

	//获取项目下的人工条目（包含系数）
	query := "select pl.code,pl.lid,nl.norm_name as name,nl.norm_unit as unit,pl.quantity,nl.norm_mechanic * nl.norm_ratio as mechanic,nl.norm_general * nl.norm_ratio as general from project_labor pl left join norm_labor nl on pl.code=nl.norm_code where pl.design_code=? and pl.design_type=? "

	args := []interface{}{pcode, designtype}
	err := dao.dbExport.Select(&laborItems, query, args...)
	if err != nil {
		logger.Errorf("failed to get labor list: %v", err)
		return nil, err
	}

	query = "select pl.code,pl.lid,nlc.rate_labor from project_labor_conversion plc left join project_labor pl  on pl.lid=plc.lid left join norm_labor_conversion nlc on plc.nci_id=nlc.id where pl.lid=?"
	type laborConversion struct {
		Code string  `db:"code"`
		Lid  string  `db:"lid"`
		Rate float64 `db:"rate_labor"`
	}

	for i := 0; i < len(laborItems); i++ {
		lid := laborItems[i].Lid
		var laborConversions []laborConversion
		var rate float64
		err := dao.dbExport.Select(&laborConversions, query, lid)
		if err != nil {
			logger.Errorf("failed to get norm conversion rate: %v", err)
			return nil, err
		}
		if len(laborConversions) > 0 {
			rate = 1
			for _, r := range laborConversions {
				rate *= r.Rate
			}

			laborItems[i].Mechanic = laborItems[i].Mechanic * rate
			laborItems[i].General = laborItems[i].General * rate
		}
	}

	return laborItems, nil
}

func (dao *exportDaoImpl) GetMaterialTable(pcode string, designtype int) ([]models.ExportXlsxTab4, error) {
	query := "SELECT pm.code,dm.mat_spec as name,dm.mat_unit as unit, pm.price,pm.quantity FROM project_material pm left join norm_material dm on pm.code=dm.mat_code WHERE design_code=? and design_type=? "
	var materiallist []models.ExportXlsxTab4
	args := []interface{}{pcode, designtype}
	err := dao.dbExport.Select(&materiallist, query, args...)
	if err != nil {
		logger.Errorf("failed to get material list: %v", err)
		return nil, err
	}
	return materiallist, nil
}

func (dao *exportDaoImpl) GetOtherFeeTable(pcode string, designtype int) ([]models.ExportXlsxTab5, error) {
	query := "select serial_number,name,basis,tax_excluded,tax,tax_included,remark from project_other where design_code=? and design_type=? "
	var otherfeelist []models.ExportXlsxTab5
	args := []interface{}{pcode, designtype}
	err := dao.dbExport.Select(&otherfeelist, query, args...)
	if err != nil {
		logger.Errorf("failed to get other fee list: %v", err)
		return nil, err
	}
	return otherfeelist, nil
}

func (dao *exportDaoImpl) GetUserByID(userID string) (models.ProjectUser, error) {
	var user models.ProjectUser
	query := "select id,user_id,user_name,org_code,org_level,created_at from bsm_user where user_id=? "
	args := []interface{}{userID}
	err := dao.dbExport.Get(&user, query, args...)
	if err != nil {
		logger.Errorf("failed to get user: %v", err)
		return models.ProjectUser{}, err
	}
	return user, nil
}

func (dao *exportDaoImpl) GetOrgByProjectCode(pcode string) (models.Org, error) {
	var org models.Org
	query := "select pb.org_code,bo.org_name,bo.org_type,bo.org_level,bo.parent_code from project_base pb left join bsm_org bo on pb.org_code=bo.org_code where pb.design_code=? "
	args := []interface{}{pcode}
	err := dao.dbExport.Get(&org, query, args...)
	if err != nil {
		logger.Errorf("failed to get org: %v", err)
		return models.Org{}, err
	}
	return org, nil
}
